#include <iostream>
#include <stdio.h>

/*
 * 多重继承有函数覆盖
 */

class Base1
{
	public:
		virtual void function_1()
		{
			printf("Base1 function_1...\n");
		}

		virtual void function_2()
		{
			printf("Base1 function_2...\n");
		}
	
};

class Base2 : public Base1
{
	public:
		virtual void function_1()
		{
			printf("Base2 function_1...\n");
		}

		virtual void function_3()
		{
			printf("Base2 function_3...\n");
		}
	
};


class Sub :  Base2
{
	public:
		virtual void function_1()
		{
			printf("Sub function_1...\n");
		}

		virtual void function_5()
		{
			printf("Sub function_5...\n");
		}
};

int main(int argc, char ** argv)
{
	Sub sub;

	printf("size = %d\n", sizeof(class Sub));	// 4。 直接继承一个父类，所以只有一个虚函数表

	printf("sub address is %x.\n", &sub);		// this 指针，是堆栈里面的地址。虚表的地址不是this指针，是this指针的前四个字节。

	/* 对象的前4字节是第一个Base1的虚表 */
	printf("sub virtual table address is:%x\n", *(int*)&sub);   		

	typedef void(*pfunction)(void);
	
	pfunction pf;

	for (int i = 0; i < 6; i++) {
		int temp = *((int*)(*(int*)&sub) + i);	
		if (temp == 0) {
			break;
		}

		pf = (pfunction)temp;
		pf();
	}

	return 0;
}

/*
	sub address is bffb2510.
	sub virtual table address is:8048a18
	Sub function_1...
	Base1 function_2...
	Base2 function_3...
	Sub function_5...
 */

#if 0
int main(int argc, char ** argv)
{
 8048700:	55                   	push   %ebp
 8048701:	89 e5                	mov    %esp,%ebp
 8048703:	83 e4 f0             	and    $0xfffffff0,%esp
 8048706:	83 ec 20             	sub    $0x20,%esp
	Sub sub;
 8048709:	8d 44 24 10          	lea    0x10(%esp),%eax
 804870d:	89 04 24             	mov    %eax,(%esp)
 8048710:	e8 89 01 00 00       	call   804889e <_ZN3SubC1Ev>

	printf("size = %d\n", sizeof(class Sub));	// 4。 直接继承一个父类，所以只有一个虚函数表
 8048715:	c7 44 24 04 04 00 00 	movl   $0x4,0x4(%esp)
 804871c:	00 
 804871d:	c7 04 24 c8 89 04 08 	movl   $0x80489c8,(%esp)
 8048724:	e8 a7 fe ff ff       	call   80485d0 <printf@plt>

	printf("sub address is %x.\n", &sub);		// this 指针，是堆栈里面的地址。虚表的地址不是this指针，是this指针的前四个字节。
 8048729:	8d 44 24 10          	lea    0x10(%esp),%eax
 804872d:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048731:	c7 04 24 d3 89 04 08 	movl   $0x80489d3,(%esp)
 8048738:	e8 93 fe ff ff       	call   80485d0 <printf@plt>

	/* 对象的前4字节是第一个Base1的虚表 */
	printf("sub virtual table address is:%x\n", *(int*)&sub);   		
 804873d:	8d 44 24 10          	lea    0x10(%esp),%eax
 8048741:	8b 00                	mov    (%eax),%eax
 8048743:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048747:	c7 04 24 e8 89 04 08 	movl   $0x80489e8,(%esp)
 804874e:	e8 7d fe ff ff       	call   80485d0 <printf@plt>

	typedef void(*pfunction)(void);
	
	pfunction pf;

	for (int i = 0; i < 6; i++) {
 8048753:	c7 44 24 1c 00 00 00 	movl   $0x0,0x1c(%esp)
 804875a:	00 
 804875b:	eb 35                	jmp    8048792 <main+0x92>
		int temp = *((int*)(*(int*)&sub) + i);	
 804875d:	8b 44 24 1c          	mov    0x1c(%esp),%eax
 8048761:	8d 14 85 00 00 00 00 	lea    0x0(,%eax,4),%edx
 8048768:	8d 44 24 10          	lea    0x10(%esp),%eax
 804876c:	8b 00                	mov    (%eax),%eax
 804876e:	01 d0                	add    %edx,%eax
 8048770:	8b 00                	mov    (%eax),%eax
 8048772:	89 44 24 18          	mov    %eax,0x18(%esp)
		if (temp == 0) {
 8048776:	83 7c 24 18 00       	cmpl   $0x0,0x18(%esp)
 804877b:	75 02                	jne    804877f <main+0x7f>
			break;
 804877d:	eb 1a                	jmp    8048799 <main+0x99>
		}

		pf = (pfunction)temp;
 804877f:	8b 44 24 18          	mov    0x18(%esp),%eax
 8048783:	89 44 24 14          	mov    %eax,0x14(%esp)
		pf();
 8048787:	8b 44 24 14          	mov    0x14(%esp),%eax
 804878b:	ff d0                	call   *%eax

	typedef void(*pfunction)(void);
	
	pfunction pf;

	for (int i = 0; i < 6; i++) {
 804878d:	83 44 24 1c 01       	addl   $0x1,0x1c(%esp)
 8048792:	83 7c 24 1c 05       	cmpl   $0x5,0x1c(%esp)
 8048797:	7e c4                	jle    804875d <main+0x5d>

		pf = (pfunction)temp;
		pf();
	}

	return 0;
 8048799:	b8 00 00 00 00       	mov    $0x0,%eax
}
 804879e:	c9                   	leave  
 804879f:	c3                   	ret    

#endif
